#include "sphere.h"

Sphere::Sphere(QString name,
               double radius,
               double refraction,
               double diffusion,
               double specularity,
               double glossy,
               double roughness,
               Vector emission,
               Vector absorbtion,
               Vector position,
               Vector rotation):
    Shape(name,
          refraction,
          diffusion,
          specularity,
          glossy,
          roughness,
          emission,
          absorbtion,
          position,
          rotation),
    _radius(radius)
{
    Vector* dots = new Vector[2]();
    dots[0] = _position;
    dots[1] = _position;
    dots[0][0] -= _radius;
    dots[1][0] += _radius;
    dots[0][1] -= _radius;
    dots[1][1] += _radius;
    dots[0][2] -= _radius;
    dots[1][2] += _radius;
    _bounds = Box(dots,6);
    delete dots;
}

double Sphere::radius() const
{
    return _radius;
}

void Sphere::setRadius(double value)
{
    _radius = value;
}

inline bool Sphere::intersect(const Ray &ray, double *distance, Vector *normal) const
{
    bool ret;
    Vector op = _position-ray.origin();
    double b=op*ray.direction();
    double det=b*b-op*op+_radius*_radius;
    if (det<=0.0)
        return false;
    det=sqrt(det);
    if((distance[_IN]=b-det)>1e-4) {
        distance[_OUT]=b+det;
        ret = true;
    }
    else if((distance[_IN]=b+det)>1e-4) {
        distance[_OUT]=b-det;
        ret =  true;
    }
    else
        ret =  false;
    Vector n[2];
    n[_IN] = Normalized(ray(distance[_IN]) - _position);
    n[_OUT] = Normalized(ray(distance[_OUT]) - _position);
    normal[_IN]= n[_IN] * ray.direction()<0 ? n[_IN] : n[_IN] * -1.0;
    normal[_OUT]= n[_OUT] * ray.direction()<0 ? n[_OUT] : n[_OUT] * -1.0;
    return ret;
}

bool Sphere::inside(const Vector &dot) const
{
    Vector op = dot - _position;
    return ((op * op - _radius * _radius) < 0.0);
}

QDataStream &operator<<(QDataStream & s, const Sphere & shpere)
{
    return s;
}

QDataStream &operator>>(QDataStream & s, Sphere & shpere)
{
    return s;
}
